// Copyright (c) 2005  INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of cgal-python; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with cgal-python.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Id: Py_Delaunay_mesher_2.cpp 172 2007-11-06 13:36:24Z spion $
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal-python/trunk/cgal-python/bindings/Mesh_2/Py_Delaunay_mesher_2.cpp $
//
// Author(s)     : Naceur Meskini
//=========================================================================
#include <CGAL/basic.h>
#include <include/approximate_sqrt.h>

#include <CGAL/Constrained_Delaunay_triangulation_2.h>

#include <CGAL/Alpha_shape_vertex_base_2.h>
#include <CGAL/Triangulation_hierarchy_vertex_base_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>

#include <CGAL/Alpha_shape_face_base_2.h>

#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_face_base_2.h>

#include <CGAL/Delaunay_mesh_size_criteria_2.h>
#include <CGAL/Delaunay_mesh_criteria_2.h>

#include "Py_Delaunay_mesher_2_doc.h"

//Boost includes===============================================================
#include <boost/python.hpp>
// #include <boost/cstdint.hpp>

#include <include/iterator.h>
#include <include/Kernels.h>


// include ====================================================================
#include <list>

// Using =======================================================================

template < class Delaunay_mesher_2,class CDT>
void set_criteria(Delaunay_mesher_2& mesher,double aspect_bound = 0.125,double size_bound = 0.0)
{
	typedef typename CGAL::Delaunay_mesh_size_criteria_2<CDT> Delaunay_mesh_size_criteria_2;
	Delaunay_mesh_size_criteria_2 criteria(aspect_bound,size_bound);

	mesher.set_criteria(criteria);
}

template < class iterator,class Delaunay_mesher_2>
simple_python_iterator<iterator> py_seeds(Delaunay_mesher_2& mesher)
{
	std::pair< iterator , iterator > p( mesher.seeds_begin(), mesher.seeds_end() );
	return simple_python_iterator<iterator>(p);
}

template < class Delaunay_mesher_2,class Point_2>
void set_seeds(Delaunay_mesher_2& mesher,boost::python::list seeds,bool mark = false)
{
	std::list<Point_2> list_of_seeds;
	for(int i = 0 ; i < seeds.attr("__len__")() ; i++ ){
		list_of_seeds.push_back(boost::python::extract<Point_2>(seeds[i]));
	}
	mesher.set_seeds(list_of_seeds.begin(),list_of_seeds.end(),mark);
}

template<class kernel>
void Py_Delaunay_mesher_2()
{
	// three things must be fixed in order to insure the derivation in the python side.
	// -1: the vertex_base 
	// -2: the face_base
	// -3: the data_structure
	typedef CGAL::Alpha_shape_vertex_base_2<kernel> 	Avb;
	typedef CGAL::Triangulation_hierarchy_vertex_base_2<Avb> Hv; //this one is needed when the input data set is huge for the Alpha_shape_2,
																 // say more than 10.000 points,
	typedef CGAL::Triangulation_vertex_base_with_info_2<boost::python::object,kernel,Hv> 	Vb;

	typedef CGAL::Delaunay_mesh_face_base_2<kernel> 	Mf; 
	typedef CGAL::Alpha_shape_face_base_2<kernel,Mf> 	Af;

	typedef CGAL::Triangulation_data_structure_2<Vb,Af> Tds;

	typedef CGAL::Constrained_Delaunay_triangulation_2<kernel, Tds,CGAL::Exact_predicates_tag> CDT;
	typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> 		Criteria;
 	typedef CGAL::Delaunay_mesher_2<CDT,Criteria> 			Delaunay_mesher_2;
 	typedef typename Delaunay_mesher_2::Seeds_iterator 		Seeds_iterator;
	typedef typename kernel::Point_2 Point_2;

	using namespace CGAL;
   	boost::python::class_< Delaunay_mesher_2 >("Delaunay_mesher_2",Delaunay_mesher_2_doc, boost::python::init< const Delaunay_mesher_2& >())
        .def(boost::python::init< CDT&, boost::python::optional< const Criteria& > >())
        .def("clear_seeds", &Delaunay_mesher_2::clear_seeds,clear_seeds_doc)
       .def("refine_mesh", &Delaunay_mesher_2::refine_mesh,refine_mesh_doc)
        .def("set_seeds", &set_seeds<Delaunay_mesher_2,Point_2>,( boost::python::arg("seeds"),boost::python::arg("mark")=false),set_seeds_doc)
        .def("set_criteria", &set_criteria<Delaunay_mesher_2,CDT>, ( boost::python::arg("aspect_bound")=0.125,boost::python::arg("size_bound")=0.0),set_criteria_doc)
        .def("init", &Delaunay_mesher_2::init,init_doc)
        .def("is_refinement_done", &Delaunay_mesher_2::is_refinement_done,is_refinement_done_doc)
        .def("step_by_step_refine_mesh", &Delaunay_mesher_2::step_by_step_refine_mesh,step_by_step_refine_mesh_doc)
//         .def("try_one_step_refine_mesh", &Delaunay_mesher_2::try_one_step_refine_mesh)
		.add_property("seeds",&py_seeds<Seeds_iterator,Delaunay_mesher_2>)
    ;

	simple_python_iterator<Seeds_iterator>::declare("Seeds_iterator");

}

void export_Delaunay_mesher_2()
{
	Py_Delaunay_mesher_2<K>();
}
